`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/06/21 16:41:57
// Design Name: 
// Module Name: miniRV
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module miniRV(
    input clk_i,
    input rst_i
    );
    
wire clk,pll;
wire locked;
wire [31:0] imm;
wire [31:0] inst;
wire [31:0] pc,pc4;
reg  [31:0] wD;
wire [31:0] rd1,rd2;
wire [31:0] alu_a,alu_b,alu_c;
wire [31:0] branch_a,branch_b;
wire [1:0]  branch_res;
wire [31:0] adr;
wire [31:0] wdin;
wire [31:0] rd;

wire [1:0]  npc_sel;
wire rf_we;
wire [1:0]  wd_sel;
wire [2:0]  sext_op;
wire [2:0]  alu_op;
wire a_sel;
wire b_sel;
wire [1:0]  branch;
wire dram_we;
wire [2:0] dram_op;

cpuclk clock(.clk_in1(clk_i),
             .locked(locked),
             .clk_out1(pll)
            );
assign clk = pll & locked; 
            
control CU(.rst(rst_i),
           .opcode(inst[6:0]),
           .funct3(inst[14:12]),
           .funct7(inst[31:25]),
           .npc_sel(npc_sel),
           .rf_we(rf_we),
           .wd_sel(wd_sel),
           .sext_op(sext_op),
           .alu_op(alu_op),
           .a_sel(a_sel),
           .b_sel(b_sel),
           .branch(branch),
           .branch_res(branch_res),
           .dram_we(dram_we),
           .dram_op(dram_op)
          );
            
ifetch IF(.rst(rst_i),
          .clk(clk),
          .imm(imm),
          .alu_c(alu_c),
          .npc_sel(npc_sel),
          .inst(inst),
          .pc(pc),
          .pc4(pc4)
         );    

always @(*)
begin
    case (wd_sel)
        2'b00:   wD = alu_c;
        2'b01:   wD = rd;
        2'b10:   wD = pc4;
        2'b11:   wD = imm;
        default: wD = 32'hzzzzzzzz;
    endcase
end

idecode ID(.rst(rst_i),
           .clk(clk),
           .wD(wD),
           .ext(imm),
           .rd1(rd1),
           .rd2(rd2),
           .inst(inst),
           .rf_we(rf_we),
           .sext_op(sext_op)
          );

assign alu_a = a_sel ? pc: rd1;
assign alu_b = b_sel ? imm: rd2;
assign branch_a = rd1;
assign branch_b = rd2;

ex EX(.rst(rst_i),
      .alu_a(alu_a),
      .alu_b(alu_b),
      .alu_c(alu_c),
      .alu_op(alu_op),
      .branch_a(branch_a),
      .branch_b(branch_b),
      .branch_res(branch_res),
      .branch(branch)
     ); 
     
assign adr = alu_c;
assign wdin = rd2;        

mem MEM(.clk(clk),
        .rst(rst_i),
        .adr(adr),
        .wdin(wdin),
        .dram_we(dram_we),
        .dram_op(dram_op),
        .rd(rd)
       );
    
endmodule
